#include <iostream>
#include "AiAgent.h"
#include "DegToRad.h"
#include "Behaviour.h"
#include "Timer.h"
#include "MainGameState.h"
#include "AntTweakBar.h"
#include "StringUtil.h"
#include "Search.h"
#include <assert.h>
#include "AiState.h"
#include "OBJManager.h"
#include "Billboard.h"

#include <glut.h>


AiAgent::AiAgent()
{
	TheOBJManager::Instance()->LoadMesh("Assets/Models/Billboard.obj", "Board");
	TheTextureManager::Instance()->LoadTexture("Assets/Textures/Walking.png", "Walking");
	m_id = -1;
	m_State = nullptr;
	m_TextureTag = "Walking";
}

AiAgent::AiAgent(Vec3f pos, int id, std::string& proffesion)
{
	TheOBJManager::Instance()->LoadMesh("Assets/Models/Billboard.obj", "Board");
	TheTextureManager::Instance()->LoadTexture("Assets/Textures/Walking.png", "Walking");
	m_Pos = pos;
	m_id = id;
	m_State = nullptr;
	m_Profession = proffesion;
	m_TextureTag = "Walking";
	//TheTweakBar::Instance()->AddVar("Agent " + ToString(m_id) + " Vel", TW_TYPE_DIR3F, &m_Vel, "");
}

void AiAgent::Update()
{
	float dt = TheTimer::Instance()->GetDeltaTime();
	
	if(m_State)
	{
		m_State->Update(this);	
	}
	else
	{
		std::cout << "Agent " << m_id << " has nothing to do, how boring.\n";
	}

	m_Vel += m_Acc * dt;

	//Clamp Vel
	if(m_Vel.Length() > 10)
	{
		m_Acc = Vec3f();
		m_Vel.Normalise();
		m_Vel *= 5;
	}



	//update pos
	m_Pos += m_Vel * dt;

	//update heading and side vectors
	//clamp vel
	if(m_Vel.Length() != 0)
	{
		m_Heading = Normalised(m_Vel);
	}
	m_Heading.m_y = 0;
}


void AiAgent::Draw()
{
	//Draw Agent
	glPushMatrix();
		glTranslatef(m_Pos.m_x, m_Pos.m_y, m_Pos.m_z);
		float angle = RadToDeg(atan2f(m_Heading.m_x, m_Heading.m_z));
		glRotatef(angle - 90, 0, 1, 0);
		glColor3f(1, 0, 0);
		glutSolidTeapot(1.0f);
		glColor3f(1, 1, 1);
	glPopMatrix();


	//Draw Billboard above agent
	glPushMatrix();
		glEnable(GL_TEXTURE_2D);
		TheTextureManager::Instance()->GetTexture(m_TextureTag);
			glDisable(GL_LIGHTING);
			glTranslatef(m_Pos.m_x, m_Pos.m_y + 2, m_Pos.m_z);
			glRotatef(RadToDeg(atan2f(m_Vel.m_x, m_Vel.m_z)), 0, 1, 0);
			TheOBJManager::Instance()->GetMesh("Board");
		glEnable(GL_LIGHTING);
		glColor3f(1, 1, 1);
	glPopMatrix();
}

void AiAgent::SetTextureTag(const std::string& newTag)
{
	m_TextureTag = newTag;
}

void AiAgent::SetAiState(AiState* newState)
{
	if(m_State != newState)
	{
		if(m_State)
		{
			delete m_State;
		}
		m_State = newState;
	}
}


void AiAgent::LoadGrapthAndPoi(const std::string file)
{
	File PoIFile;
	PoIFile.OpenRead(file);
	std::string line;

	while(PoIFile.GetString(&line))
	{
		Strings str = Split(line, ' ');
		if(str[0] == "PointOfInterest")
		{
			PointOfInterest TempPoi(Vec3f(ToFloat(str[1]), ToFloat(str[2]), ToFloat(str[3])), ToFloat(str[4]), ToFloat(str[5]));
			//Get texture info
			PoIFile.GetString(&line);
			Strings str = Split(line, ' ');
			TheTextureManager::Instance()->LoadTexture(str[0], str[1]);
			TempPoi.SetTexTag(str[1]);
			m_PoIvec.push_back(TempPoi);
			continue;
		}

		if(str[0] == "GraphNode")
		{
			GraphNode TempNode(Vec3f(ToFloat(str[1]), ToFloat(str[2]), ToFloat(str[3])));
			m_Graph.AddNode(TempNode);
			continue;
		}

		if(str[0] == "GraphEdge")
		{
			GraphEdge tempEdge(ToInt(str[1]), ToInt(str[2]), ToFloat(str[3]));
			m_Graph.AddEdge(tempEdge);
			continue;
		}
	}
#ifdef _DEBUG
	m_Graph.Test();
#endif // DEBUG
}

void AiAgent::SetPath(std::vector<int>& newPath)
{
	m_Path = newPath;
}

std::vector<int>& AiAgent::GetPath()
{
	return m_Path;
}

void AiAgent::SetVel(Vec3f newVel)
{
	m_Vel = newVel;
}

void AiAgent::SetAcc(Vec3f newAcc)
{
	m_Acc = newAcc;
}

AiAgent::~AiAgent()
{
	//if(m_State)
	//{
	//	delete m_State;
	//}
}